home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / game / think / MUIMineSrc.lha / MUIMineSource / LevelData.c < prev    next >
C/C++ Source or Header  |  1998-12-14  |  14KB  |  481 lines

  1. /*
  2.     LevelData implementation for MUIMine
  3. */
  4. #include "MUIMine.h"
  5. #include "MFStrings.h"
  6. #include "MFWindow.h"
  7. #include "LevelData.h"
  8.  
  9.  
  10.  
  11. /*
  12.     level data file header structure
  13. */
  14. #define LEVEL_HEADER_ID_SIZE      8
  15. #define LEVEL_HEADER_ID_STRING    "MFLEVELS"
  16.  
  17. struct LevelDataFileHeader
  18. {
  19.     char    IdString[LEVEL_HEADER_ID_SIZE];
  20.     LONG    NumLevels;
  21.     ULONG   CurrentLevel;
  22. };
  23.  
  24. /*
  25.     defines
  26. */
  27.  
  28. #define DEFAULT_LEVEL_FILE_NAME (STRPTR)"PROGDIR:MUIMineLevelData"
  29.  
  30.  
  31. /*
  32.     LevelDataList.Flags defines
  33. */
  34. #define LDLF_STATIC_DATA        0x00000001
  35.  
  36.  
  37.  
  38. /*
  39.     default LevelData
  40. */
  41. #define NUM_DEF_LEVELS  3
  42. struct LevelData defLevelData[NUM_DEF_LEVELS] =
  43. {
  44.     {MUIV_MFWindow_Level_Beginner,     MSG_LEVEL_BEGINNER,     NULL, "Beginner",     {{-1, ""}, {-1, ""}, {-1, ""}}},
  45.     {MUIV_MFWindow_Level_Intermediate, MSG_LEVEL_INTERMEDIATE, NULL, "Intermediate", {{-1, ""}, {-1, ""}, {-1, ""}}},
  46.     {MUIV_MFWindow_Level_Expert,       MSG_LEVEL_EXPERT,       NULL, "Expert",       {{-1, ""}, {-1, ""}, {-1, ""}}}
  47. };
  48.  
  49.  
  50. /*
  51.     function :    loads the level data from a disk file, allocates and
  52.                   initialize memory for the level array with data from
  53.                   the disk file if it was successfully loaded or with
  54.                   the default level data if the disk load failed
  55.  
  56.     parameters :  lList = pointer to a LevelDataList that is initialized
  57.                           with the level data
  58.                   fileName = pointer to name of level data file, if NULL
  59.                              use the default level file name
  60.  
  61.     return :      TRUE if the LevelDataList was fully initialized
  62. */
  63. BOOL LoadLevelData(struct LevelDataList *lList, STRPTR fileName)
  64. {
  65.     BOOL ret = FALSE;
  66.     BPTR fileHandle;
  67.     LONG size;
  68.     int numLevels = 0;
  69.     ULONG currLevel = 0;
  70.  
  71.     /*
  72.         attempt to open existing level data file
  73.     */
  74.     fileHandle = Open(((fileName) ? fileName
  75.                                   : DEFAULT_LEVEL_FILE_NAME),
  76.                               MODE_OLDFILE);
  77.  
  78.     if (fileHandle)
  79.     {
  80.         struct LevelDataFileHeader header;
  81.         /*
  82.             determine if this is a valid level data file by reading
  83.             the file header and checking the id string and comparing
  84.             the file size with the size calculated for the number of
  85.             levels given in the header
  86.         */
  87.         if (Read(fileHandle, (APTR)&header, sizeof(struct LevelDataFileHeader))
  88.                     == sizeof(struct LevelDataFileHeader))
  89.         {
  90.             int i;
  91.             char * p1, * p2;
  92.  
  93.             /*
  94.                 check the header id string
  95.             */
  96.             p1 = header.IdString;
  97.             p2 = LEVEL_HEADER_ID_STRING;
  98.             for (i = LEVEL_HEADER_ID_SIZE; i > 0; i--)
  99.             {
  100.                 if (*p1++ != *p2++)
  101.                 {
  102.                     break;
  103.                 }
  104.             }
  105.             if (i == 0)
  106.             {
  107.                 /*
  108.                     id string checked out ok, now get the file size
  109.                 */
  110.                 struct FileInfoBlock fib;
  111.                 if (ExamineFH(fileHandle, &fib))
  112.                 {
  113.                     /*
  114.                         check that the file size is the size of the file
  115.                         header plus the size of LevelData structure times
  116.                         the number of levels given in the header
  117.                     */
  118.                     size = fib.fib_Size - sizeof(struct LevelDataFileHeader);;
  119.                     if (size  ==  header.NumLevels * sizeof(struct LevelData))
  120.                     {
  121.                         /*
  122.                             set the number of levels to allocate for
  123.                         */
  124.                         numLevels = header.NumLevels;
  125.                         currLevel = header.CurrentLevel;
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.     }
  131.  
  132.     /*
  133.         initialize the level data list for the number of levels
  134.         in the data file if it exists otherwise use the number
  135.         of default levels
  136.     */
  137.     if (InitLevelDataList(lList, (numLevels) ? numLevels : NUM_DEF_LEVELS))
  138.     {
  139.         /*
  140.             buffer was allocated now read the level data from the file
  141.             if it was opened and contains level data otherwise copy the
  142.             default level data
  143.         */
  144.         if (numLevels)
  145.         {
  146.             /*
  147.                 buffer was allocated now read the data from the file
  148.             */
  149.             if (Read(fileHandle, (APTR)lList->LevelList, size) == size)
  150.             {
  151.                 int i;
  152.                 struct LevelData * pLevel;
  153.                 /*
  154.                     the level data was read from the file to the allocated
  155.                     buffer, initialize the LevelDataList with the loaded data
  156.                 */
  157.                 lList->CurrentLevel = currLevel;
  158.                 /*
  159.                     clear the menu data members of the LevelData's as the
  160.                     data that was last saved is obsolete and needs to be
  161.                     initialized
  162.                 */
  163.                 for (i = lList->NumLevels, pLevel = lList->LevelList;
  164.                      i > 0;
  165.                      i--, pLevel++)
  166.                 {
  167.                     pLevel->MenuId = 0;
  168.                     pLevel->MenuItem = NULL;
  169.                 }
  170.                 /*
  171.                     set the return flag to success
  172.                 */
  173.                 ret = TRUE;
  174.             }
  175.             else
  176.             {
  177.                 /*
  178.                     failed to read the file, delete the allocate buffer
  179.                     and use the default level data
  180.                 */
  181.                 FreeVec((APTR)lList->LevelList);
  182.                 lList->NumLevels = 0;
  183.                 lList->LevelList = NULL;
  184.             }
  185.         }
  186.         else
  187.         {
  188.             /*
  189.                 level data file was not opened, copy the default level
  190.                 data to the allocated buffer
  191.             */
  192.             int i;
  193.             STRPTR p;
  194.             struct LevelData *p1, *p2;
  195.  
  196.             for (i = 0, p1 = lList->LevelList, p2 = defLevelData;
  197.                  i < NUM_DEF_LEVELS;
  198.                  i++, p1++, p2++)
  199.             {
  200.                 *p1 = *p2;
  201.                 p = GetStr((LONG)defLevelData[i].MenuId);
  202.                 if (p)
  203.                 {
  204.                     strcpy(p1->Name, p);
  205.                 }
  206.             }
  207.  
  208.             /*
  209.                 set the level data in the LevelDataList
  210.             */
  211.             lList->CurrentLevel = lList->LevelList->Level;
  212.  
  213.             ret = TRUE; // set return code to success
  214.         }
  215.     }
  216.  
  217.     /*
  218.         close the level data file if it was opened
  219.     */
  220.     if (fileHandle)
  221.     {
  222.         Close(fileHandle);
  223.     }
  224.  
  225.     /*
  226.         if the level data was not loaded from the file then use the
  227.         default level data list
  228.     */
  229.     if (lList->LevelList == NULL)
  230.     {
  231.         lList->NumLevels = NUM_DEF_LEVELS;
  232.         lList->Flags |= LDLF_STATIC_DATA;
  233.         lList->LevelList = defLevelData;
  234.         lList->CurrentLevel = lList->LevelList->Level;
  235.         ret = TRUE;
  236.     }
  237.  
  238.     /*
  239.         return the success flag
  240.     */
  241.     return ret;
  242. }
  243.  
  244. /*
  245.     function :    saves the level data list to a disk file
  246.  
  247.     parameters :  lList = pointer to the level data list to save
  248.                   fileName = pointer to name of file to save to, if NULL
  249.                              then save to the default file
  250.  
  251.     return :      TRUE if data was rwitten successfully, FALSE otherwise
  252. */
  253. BOOL SaveLevelData(struct LevelDataList * lList, STRPTR fileName)
  254. {
  255.     BOOL ret = FALSE;
  256.  
  257.     /*
  258.         only save data if there is something to save
  259.     */
  260.     if (lList  &&  lList->LevelList  &&  lList->NumLevels != 0)
  261.     {
  262.         /*
  263.             attempt to open the file as a new file
  264.         */
  265.         BPTR fileHandle = Open(((fileName) ? fileName : DEFAULT_LEVEL_FILE_NAME),
  266.                                 MODE_NEWFILE);
  267.         if (fileHandle)
  268.         {
  269.             struct LevelDataFileHeader header;
  270.             int i;
  271.             char *p1, *p2;
  272.  
  273.             /*
  274.                 fill in the file header, copy the id string, set the
  275.                 number of levels and the current level
  276.             */
  277.             p1 = header.IdString;
  278.             p2 = LEVEL_HEADER_ID_STRING;
  279.             for (i = LEVEL_HEADER_ID_SIZE; i > 0; i--)
  280.             {
  281.                 *p1++ = *p2++;
  282.             }
  283.             header.NumLevels = lList->NumLevels;
  284.             header.CurrentLevel = lList->CurrentLevel;
  285.  
  286.             /*
  287.                 write the header to the file
  288.             */
  289.             if (Write(fileHandle, (APTR)&header, sizeof(struct LevelDataFileHeader))
  290.                         ==  sizeof(struct LevelDataFileHeader))
  291.             {
  292.                 /*
  293.                     calculate the size of the level data to write to the
  294.                     file and write the level data to the file setting the
  295.                     return code to the success of the write
  296.                 */
  297.                 LONG size = lList->NumLevels * sizeof(struct LevelData);
  298.                 ret = (Write(fileHandle, (APTR)lList->LevelList, size)
  299.                             == size);
  300.             }
  301.  
  302.             /*
  303.                 close the file
  304.             */
  305.             Close(fileHandle);
  306.         }
  307.     }
  308.  
  309.     return ret;     // return success code
  310. }
  311.  
  312. /*
  313.     function :    initializes a level data list, by allocating a level
  314.                   data array and initializing the list's members
  315.  
  316.     parameters:   lList = pointer to the level data list to initialize
  317.                   numLevels = number of levels to allocate
  318.  
  319.     return :      TRUE if level data was allocated, FALSE otherwise
  320. */
  321. BOOL InitLevelDataList(struct LevelDataList * lList, int numLevels)
  322. {
  323.     BOOL ret = FALSE;
  324.  
  325.     /*
  326.         initialize members
  327.     */
  328.     lList->NumLevels = 0;
  329.     lList->Flags = 0;
  330.     lList->CurrentLevel = 0;
  331.     lList->LevelList = NULL;
  332.  
  333.     /*
  334.         check number of levels parameter
  335.     */
  336.     if (numLevels > 0)
  337.     {
  338.         /*
  339.             attempt to allocate the level data array
  340.         */
  341.         lList->LevelList = (struct LevelData *)AllocVec(
  342.                                         numLevels * sizeof(struct LevelData),
  343.                                         MEMF_CLEAR);
  344.         if (lList->LevelList)
  345.         {
  346.             /*
  347.                 level data array allocated, set the NumLevels member
  348.                 to the number of allocated levels and set the return
  349.                 code to TRUE to indicate that level data was allocated
  350.             */
  351.             lList->NumLevels = numLevels;
  352.             ret = TRUE;
  353.         }
  354.     }
  355.  
  356.     return ret;
  357. }
  358.  
  359. /*
  360.     function :    dispose of allocated level data
  361.  
  362.     parameters :  lList = pointer to the level data list to dispose of
  363.  
  364.     return :      none
  365. */
  366. void DisposeLevelData(struct LevelDataList * lList)
  367. {
  368.     if (lList)
  369.     {
  370.         if ((lList->Flags & LDLF_STATIC_DATA) == 0  &&
  371.             lList->LevelList)
  372.         {
  373.             FreeVec((APTR)lList->LevelList);
  374.         }
  375.         lList->NumLevels = 0;
  376.         lList->Flags = 0;
  377.         lList->LevelList = NULL;
  378.     }
  379. }
  380.  
  381.  
  382. /*
  383.     function :    searches a LevelDataList for a LevelData for the given level
  384.  
  385.     parameters :  lList = pointer to the LevelDataList to search
  386.                   level = level to search for
  387.  
  388.     return :      pointer to the LevelData if found, NULL otherwise
  389. */
  390. struct LevelData * FindLevel(struct LevelDataList * lList, ULONG level)
  391. {
  392.     struct LevelData * ret = NULL;
  393.  
  394.     /*
  395.         check for list and non-NULL level
  396.     */
  397.     if (lList  &&  level)
  398.     {
  399.         int i;
  400.         struct LevelData * pLevel;
  401.  
  402.         /*
  403.             step through list comparing each level's Level member
  404.             to the level being searched for
  405.         */
  406.         for (i = lList->NumLevels, pLevel = lList->LevelList;
  407.              i > 0;
  408.              i--, pLevel++)
  409.         {
  410.             if (pLevel->Level == level)
  411.             {
  412.                 /*
  413.                     the level was found, set the return vale to the found
  414.                     level and exit the search loop
  415.                 */
  416.                 ret = pLevel;
  417.                 break;
  418.             }
  419.         }
  420.     }
  421.  
  422.     return ret;
  423. }
  424.  
  425.  
  426. /*
  427.     function :    searches a LevelDataList for a LevelData with a given menu id
  428.  
  429.     parameters :  lList = pointer to the LevelDataList to search
  430.                   menuId = menu id to search for
  431.  
  432.     return :      pointer to the LevelData if found, NULL otherwise
  433. */
  434. struct LevelData * FindMenuId(struct LevelDataList * lList, ULONG menuId)
  435. {
  436.     struct LevelData * ret = NULL;
  437.  
  438.     /*
  439.         check for list and non-NULL menu id
  440.     */
  441.     if (lList  &&  menuId)
  442.     {
  443.         int i;
  444.         struct LevelData * pLevel;
  445.  
  446.         /*
  447.             step through the list comparing each level's MenuId member
  448.             to the menu id being searched for
  449.         */
  450.         for (i = lList->NumLevels, pLevel = lList->LevelList;
  451.              i > 0;
  452.              i--, pLevel++)
  453.         {
  454.             if (pLevel->MenuId == menuId)
  455.             {
  456.                 /*
  457.                     the menu id was found, set the return value to this
  458.                     level and exit the search loop
  459.                 */
  460.                 ret = pLevel;
  461.                 break;
  462.             }
  463.         }
  464.     }
  465.  
  466.     return ret;
  467. }
  468.  
  469. /*
  470.     function :    searches a LevelDataList for the current LevelData
  471.  
  472.     parameters :  lList = pointer to the LevelDataList to search
  473.  
  474.     return :      pointer to the LevelData if found, NULL otherwise
  475. */
  476. struct LevelData * FindCurrentLevel(struct LevelDataList * lList)
  477. {
  478.     return FindLevel(lList, lList->CurrentLevel);
  479. }
  480.  
  481.